home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / inkscape / extensions / funcplot.py < prev    next >
Encoding:
Python Source  |  2010-03-12  |  11.3 KB  |  278 lines

  1. #!/usr/bin/env python 
  2. '''
  3. Copyright (C) 2007 Tavmjong Bah, tavmjong@free.fr
  4. Copyright (C) 2006 Georg Wiora, xorx@quarkbox.de
  5. Copyright (C) 2006 Johan Engelen, johan@shouraizou.nl
  6. Copyright (C) 2005 Aaron Spike, aaron@ekips.org
  7.  
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12.  
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21.  
  22. Changes:
  23.  * This program is a modified version of wavy.py by Aaron Spike.
  24.  * 22-Dec-2006: Wiora : Added axis and isotropic scaling
  25.  * 21-Jun-2007: Tavmjong: Added polar coordinates
  26.  
  27. '''
  28. import inkex, simplepath, simplestyle
  29. from math import *
  30. from random import *
  31.  
  32. def drawfunction(xstart, xend, ybottom, ytop, samples, width, height, left, bottom, 
  33.     fx = "sin(x)", fpx = "cos(x)", fponum = True, times2pi = False, polar = False, isoscale = True, drawaxis = True):
  34.  
  35.     if times2pi == True:
  36.         xstart = 2 * pi * xstart
  37.         xend   = 2 * pi * xend   
  38.       
  39.     # coords and scales based on the source rect
  40.     scalex = width / (xend - xstart)
  41.     xoff = left
  42.     coordx = lambda x: (x - xstart) * scalex + xoff  #convert x-value to coordinate
  43.     if polar :  # Set scale so that left side of rectangle is -1, right side is +1.
  44.                 # (We can't use xscale for both range and scale.)
  45.         centerx = left + width/2.0
  46.         polar_scalex = width/2.0
  47.         coordx = lambda x: x * polar_scalex + centerx  #convert x-value to coordinate
  48.  
  49.     scaley = height / (ytop - ybottom)
  50.     yoff = bottom
  51.     coordy = lambda y: (ybottom - y) * scaley + yoff  #convert y-value to coordinate
  52.  
  53.     # Check for isotropic scaling and use smaller of the two scales, correct ranges
  54.     if isoscale and not polar:
  55.       if scaley<scalex:
  56.         # compute zero location
  57.         xzero = coordx(0)
  58.         # set scale
  59.         scalex = scaley
  60.         # correct x-offset
  61.         xstart = (left-xzero)/scalex
  62.         xend = (left+width-xzero)/scalex
  63.       else :
  64.         # compute zero location
  65.         yzero = coordy(0)
  66.         # set scale
  67.         scaley = scalex
  68.         # correct x-offset
  69.         ybottom = (yzero-bottom)/scaley
  70.         ytop = (bottom+height-yzero)/scaley
  71.  
  72.     # functions specified by the user
  73.     if fx != "":
  74.         f = eval('lambda x: ' + fx.strip('"'))
  75.     if fpx != "":
  76.         fp = eval('lambda x: ' + fpx.strip('"'))
  77.  
  78.     # step is the distance between nodes on x
  79.     step = (xend - xstart) / (samples-1)
  80.     third = step / 3.0
  81.     ds = step * 0.001 # Step used in calculating derivatives
  82.  
  83.     a = [] # path array 
  84.     # add axis
  85.     if drawaxis :
  86.       # check for visibility of x-axis
  87.       if ybottom<=0 and ytop>=0:
  88.         # xaxis
  89.         a.append(['M ',[left, coordy(0)]])
  90.         a.append([' l ',[width, 0]])
  91.       # check for visibility of y-axis
  92.       if xstart<=0 and xend>=0:
  93.         # xaxis
  94.         a.append([' M ',[coordx(0),bottom]])
  95.         a.append([' l ',[0, -height]])
  96.  
  97.     # initialize function and derivative for 0;
  98.     # they are carried over from one iteration to the next, to avoid extra function calculations. 
  99.     x0 =   xstart
  100.     y0 = f(xstart)
  101.     if polar :
  102.         xp0 = y0 * cos( x0 )
  103.         yp0 = y0 * sin( x0 )
  104.         x0 = xp0
  105.         y0 = yp0
  106.     if fponum or polar: # numerical derivative, using 0.001*step as the small differential
  107.         x1 = xstart + ds # Second point AFTER first point (Good for first point)
  108.         y1 = f(x1)
  109.         if polar :
  110.             xp1 = y1 * cos( x1 )
  111.             yp1 = y1 * sin( x1 )
  112.             x1 = xp1
  113.             y1 = yp1
  114.         dx0 = (x1 - x0)/ds 
  115.         dy0 = (y1 - y0)/ds
  116.     else: # derivative given by the user
  117.         dx0 = 1 # Only works for rectangular coordinates
  118.         dy0 = fp(xstart)
  119.  
  120.     # Start curve
  121.     a.append([' M ',[coordx(x0), coordy(y0)]]) # initial moveto
  122.  
  123.     for i in range(int(samples-1)):
  124.         x1 = (i+1) * step + xstart
  125.         x2 = x1 - ds # Second point BEFORE first point (Good for last point)
  126.         y1 = f(x1)
  127.         y2 = f(x2)
  128.         if polar :
  129.             xp1 = y1 * cos( x1 )
  130.             yp1 = y1 * sin( x1 )
  131.             xp2 = y2 * cos( x2 )
  132.             yp2 = y2 * sin( x2 )
  133.             x1 = xp1
  134.             y1 = yp1
  135.             x2 = xp2
  136.             y2 = yp2
  137.         if fponum or polar: # numerical derivative
  138.             dx1 = (x1 - x2)/ds
  139.             dy1 = (y1 - y2)/ds
  140.         else: # derivative given by the user
  141.             dx1 = 1 # Only works for rectangular coordinates
  142.             dy1 = fp(x1)
  143.         # create curve
  144.         a.append([' C ',
  145.                   [coordx(x0 + (dx0 * third)), coordy(y0 + (dy0 * third)), 
  146.                    coordx(x1 - (dx1 * third)), coordy(y1 - (dy1 * third)),
  147.                    coordx(x1),                 coordy(y1)]
  148.                   ])
  149.         x0  = x1  # Next segment's start is this segments end
  150.         y0  = y1
  151.         dx0 = dx1 # Assume the function is smooth everywhere, so carry over the derivative too
  152.         dy0 = dy1    
  153.     return a
  154.  
  155. class FuncPlot(inkex.Effect):
  156.     def __init__(self):
  157.         inkex.Effect.__init__(self)
  158.         self.OptionParser.add_option("--xstart",
  159.                         action="store", type="float", 
  160.                         dest="xstart", default=0.0,
  161.                         help="Start x-value")
  162.         self.OptionParser.add_option("--xend",
  163.                         action="store", type="float", 
  164.                         dest="xend", default=1.0,
  165.                         help="End x-value")
  166.         self.OptionParser.add_option("--times2pi",
  167.                         action="store", type="inkbool", 
  168.                         dest="times2pi", default=True,
  169.                         help="Multiply x-range by 2*pi")    
  170.         self.OptionParser.add_option("--polar",
  171.                         action="store", type="inkbool", 
  172.                         dest="polar", default=False,
  173.                         help="Plot using polar coordinates")    
  174.         self.OptionParser.add_option("--ybottom",
  175.                         action="store", type="float", 
  176.                         dest="ybottom", default=-1.0,
  177.                         help="y-value of rectangle's bottom")
  178.         self.OptionParser.add_option("--ytop",
  179.                         action="store", type="float", 
  180.                         dest="ytop", default=1.0,
  181.                         help="y-value of rectangle's top")
  182.         self.OptionParser.add_option("-s", "--samples",
  183.                         action="store", type="int", 
  184.                         dest="samples", default=8,
  185.                         help="Samples")    
  186.         self.OptionParser.add_option("--fofx",
  187.                         action="store", type="string", 
  188.                         dest="fofx", default="sin(x)",
  189.                         help="f(x) for plotting")    
  190.         self.OptionParser.add_option("--fponum",
  191.                         action="store", type="inkbool", 
  192.                         dest="fponum", default=True,
  193.                         help="Calculate the first derivative numerically")    
  194.         self.OptionParser.add_option("--fpofx",
  195.                         action="store", type="string", 
  196.                         dest="fpofx", default="cos(x)",
  197.                         help="f'(x) for plotting") 
  198.         self.OptionParser.add_option("--remove",
  199.                         action="store", type="inkbool", 
  200.                         dest="remove", default=True,
  201.                         help="If True, source rectangle is removed") 
  202.         self.OptionParser.add_option("--isoscale",
  203.                         action="store", type="inkbool", 
  204.                         dest="isoscale", default=True,
  205.                         help="If True, isotropic scaling is used") 
  206.         self.OptionParser.add_option("--drawaxis",
  207.                         action="store", type="inkbool", 
  208.                         dest="drawaxis", default=True,
  209.                         help="If True, axis are drawn") 
  210.         self.OptionParser.add_option("--tab",
  211.                         action="store", type="string", 
  212.                         dest="tab", default="sampling",
  213.                         help="The selected UI-tab when OK was pressed") 
  214.         self.OptionParser.add_option("--funcplotuse",
  215.                         action="store", type="string", 
  216.                         dest="funcplotuse", default="",
  217.                         help="dummy") 
  218.         self.OptionParser.add_option("--pythonfunctions",
  219.                         action="store", type="string", 
  220.                         dest="pythonfunctions", default="",
  221.                         help="dummy") 
  222.  
  223.     def effect(self):
  224.         for id, node in self.selected.iteritems():
  225.             if node.tag == inkex.addNS('rect','svg'):
  226.                 # create new path with basic dimensions of selected rectangle
  227.                 newpath = inkex.etree.Element(inkex.addNS('path','svg'))
  228.                 x = float(node.get('x'))
  229.                 y = float(node.get('y'))
  230.                 w = float(node.get('width'))
  231.                 h = float(node.get('height'))
  232.  
  233.                 #copy attributes of rect
  234.                 s = node.get('style')
  235.                 if s:
  236.                     newpath.set('style', s)
  237.                 
  238.                 t = node.get('transform')
  239.                 if t:
  240.                     newpath.set('transform', t)
  241.                     
  242.                 # top and bottom were exchanged
  243.                 newpath.set('d', simplepath.formatPath(
  244.                             drawfunction(self.options.xstart,
  245.                                 self.options.xend,
  246.                                 self.options.ybottom,
  247.                                 self.options.ytop,
  248.                                 self.options.samples, 
  249.                                 w,h,x,y+h,
  250.                                 self.options.fofx, 
  251.                                 self.options.fpofx,
  252.                                 self.options.fponum,
  253.                                 self.options.times2pi,
  254.                                 self.options.polar,
  255.                                 self.options.isoscale,
  256.                                 self.options.drawaxis)))
  257.                 newpath.set('title', self.options.fofx)
  258.                 
  259.                 #newpath.setAttribute('desc', '!func;' + self.options.fofx + ';' 
  260.                 #                                      + self.options.fpofx + ';'
  261.                 #                                      + `self.options.fponum` + ';'
  262.                 #                                      + `self.options.xstart` + ';'
  263.                 #                                      + `self.options.xend` + ';'
  264.                 #                                      + `self.options.samples`)
  265.                                 
  266.                 # add path into SVG structure
  267.                 node.getparent().append(newpath)
  268.                 # option wether to remove the rectangle or not.
  269.                 if self.options.remove:
  270.                     node.getparent().remove(node)
  271.                 
  272. if __name__ == '__main__':
  273.     e = FuncPlot()
  274.     e.affect()
  275.  
  276.  
  277. # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
  278.